package com.zlkj.pro.core.util;

import org.springframework.beans.BeanUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 泛型转换工具
 *
 * @author 孙铭泽
 * @date 2020-10-28
 * @time 11:01
 **/
public class ConvertUtil {

    private ConvertUtil() {
        throw new IllegalStateException();
    }

    /**
     * dto集合转换vo集合
     *
     * @param source 源集合
     * @param vClass 需转换成泛型对象
     * @return 根据类型转换结果
     */
    public static <D, V> List<V> turn(List<D> source, Class<V> vClass) {
        return Optional
                .ofNullable(source)
                .orElse(Collections.emptyList())
                .stream()
                .map(d -> turn(d, vClass))
                .collect(Collectors.toList());
    }

    /**
     * dto转换vo
     *
     * @param source 原类型
     * @param vClass 需转换成泛型对象
     * @return 根据类型转结果
     */
    public static <D, V> V turn(D source, Class<V> vClass) {
        V v = newInstance(vClass);
        assert v != null;
        if (Objects.isNull(source)) {
            return v;
        }
        BeanUtils.copyProperties(source, v);
        return v;
    }

    /**
     * dto转换vo
     *
     * @param source     原类型
     * @param vClass     需转换成泛型对象
     * @param returnNull 如果源为空是否返回空
     * @return 根据类型转结果
     */
    public static <D, V> V turn(D source, Class<V> vClass, boolean returnNull) {
        V v = newInstance(vClass);
        assert v != null;
        boolean aNull = Objects.isNull(source);
        if (returnNull && aNull) {
            return null;
        } else if (aNull) {
            return v;
        }
        BeanUtils.copyProperties(source, v);
        return v;
    }

    /**
     * 获取新对象
     *
     * @param aClass 对象类
     * @return 返回新对象
     */
    private static <T> T newInstance(Class<T> aClass) {
        T t = null;
        try {
            t = aClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }

}
